home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / drdobbs / 1991 / 05 / d_flat / textbox.c < prev    next >
Text File  |  1991-02-19  |  11KB  |  457 lines

  1. /* ------------- textbox.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <dos.h>
  7. #include "dflat.h"
  8.  
  9. static char *GetTextLine(WINDOW wnd, int selection);
  10.  
  11. static int HScrolling = FALSE;
  12. static int VScrolling = FALSE;
  13.  
  14. int TextBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  15. {
  16.     int    mx = (int) p1 - GetLeft(wnd);
  17.     int    my = (int) p2 - GetTop(wnd);
  18.     switch (msg)    {
  19.         case CREATE_WINDOW:
  20.             wnd->wlines = wnd->wtop = wnd->wleft =
  21.                 wnd->textlen = wnd->textwidth = 0;
  22.             wnd->text = NULL;
  23.             wnd->HScrollBox = wnd->VScrollBox = 1;
  24.             ClearBlock(wnd);
  25.             break;
  26.         case ADDTEXT:    {
  27.             /* ======== need to assure that length !> 64K ======= */
  28.             int adln = strlen((char *)p1)+2;
  29.             if (wnd->text != NULL)    {
  30.                 int txln = strlen(wnd->text);
  31.                 if (txln+adln > wnd->textlen)    {
  32.                     wnd->text = realloc(wnd->text, txln+adln);
  33.                     wnd->textlen = txln+adln-1;
  34.                 }
  35.             }
  36.             else    {
  37.                 wnd->text = malloc(adln);
  38.                 *wnd->text = '\0';
  39.                 wnd->textlen = adln-1;
  40.             }
  41.             strcat(wnd->text, (char*) p1);
  42.             strcat(wnd->text, "\n");
  43.             wnd->wlines++;
  44.             wnd->textwidth = max(adln, wnd->textwidth);
  45.             break;
  46.         }
  47.         case SETTEXT:    {
  48.             char *cp, *cp1;
  49.             SendMessage(wnd, CLEARTEXT, 0, 0);
  50.             wnd->text = cp = cp1 = (void *) p1;
  51.             wnd->textlen = max(strlen(cp)+1, (int) p2);
  52.             while ((cp = strchr(cp, '\n')) != NULL)    {
  53.                 wnd->wlines++;
  54.                 cp++;
  55.                 wnd->textwidth = max(wnd->textwidth, (int)(cp-cp1));
  56.                 cp1 = cp;
  57.             }
  58.             break;
  59.         }
  60.         case CLEARTEXT:
  61.             if (wnd->text != NULL)
  62.                 free(wnd->text);
  63.             wnd->text = NULL;
  64.             wnd->textlen = 0;
  65.             wnd->wlines = 0;
  66.             wnd->textwidth = 0;
  67.             wnd->wtop = wnd->wleft = 0;
  68.             ClearBlock(wnd);
  69.             break;
  70.         case SETFOCUS:
  71.             if (!p1 && isMultiLine(wnd))
  72.                 ClearBlock(wnd);
  73.             break;
  74.         case KEYBOARD:
  75.             if (WindowMoving || WindowSizing)
  76.                 break;
  77.             switch ((int) p1)    {
  78.                 case UP:
  79.                     if (wnd->wtop)
  80.                         SendMessage(wnd, SCROLL, FALSE, 0);
  81.                     return TRUE;
  82.                 case DN:
  83.                     if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)
  84.                         SendMessage(wnd, SCROLL, TRUE, 0);
  85.                     return TRUE;
  86.                 case FWD:
  87.                     SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  88.                     return TRUE;
  89.                 case BS:
  90.                     SendMessage(wnd, HORIZSCROLL, FALSE, 0);
  91.                     return TRUE;
  92.                 case PGUP:
  93.                     if (wnd->wtop)    {
  94.                         wnd->wtop -= ClientHeight(wnd);
  95.                         if (wnd->wtop < 0)
  96.                             wnd->wtop = 0;
  97.                         SendMessage(wnd, PAINT, 0, 0);
  98.                         return TRUE;
  99.                     }
  100.                     return TRUE;
  101.                 case PGDN:
  102.                     if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)    {
  103.                         wnd->wtop += ClientHeight(wnd);
  104.                         if (wnd->wtop > wnd->wlines-ClientHeight(wnd))
  105.                             wnd->wtop = wnd->wlines-ClientHeight(wnd);
  106.                         SendMessage(wnd, PAINT, 0, 0);
  107.                         return TRUE;
  108.                     }
  109.                     return TRUE;
  110.                 case HOME:
  111.                     if (wnd->wtop || wnd->wleft)    {
  112.                         wnd->wtop = wnd->wleft = 0;
  113.                         SendMessage(wnd, PAINT, 0, 0);
  114.                     }
  115.                     return TRUE;
  116.                 case END:
  117.                     if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)    {
  118.                         wnd->wtop = wnd->wlines-ClientHeight(wnd);
  119.                         wnd->wleft = 0;
  120.                         SendMessage(wnd, PAINT, 0, 0);
  121.                     }
  122.                     return TRUE;
  123.                 default:
  124.                     break;
  125.             }
  126.             break;
  127.         case LEFT_BUTTON:
  128.             if (WindowSizing || WindowMoving)
  129.                 return FALSE;
  130.             if (TestAttribute(wnd, VSCROLLBAR) && (VScrolling ||
  131.                     mx == WindowWidth(wnd)-1))    {
  132.  
  133.                 /* -------- in the right border ------- */
  134.                 if (my == 0 || my == ClientHeight(wnd)+1)
  135.                     /* ------ above or below the scroll bar ---- */
  136.                     break;
  137.  
  138.                 /* ---------- in the scroll bar ----------- */
  139.  
  140.                 VScrolling = TRUE;
  141.  
  142.                 if (my == 1)    {
  143.                     /* -------- top scroll button --------- */
  144.                     SendMessage(wnd, SCROLL, FALSE, 0);
  145.                     return TRUE;
  146.                 }
  147.                 if (my == ClientHeight(wnd))    {
  148.                     /* -------- bottom scroll button --------- */
  149.                     SendMessage(wnd, SCROLL, TRUE, 0);
  150.                     return TRUE;
  151.                 }
  152.                 if (my-1 != wnd->VScrollBox)    {
  153.                     int dir = my-1 > wnd->VScrollBox;
  154.  
  155.                     while (dir ? (my-1 > wnd->VScrollBox) :
  156.                                  (my-1 < wnd->VScrollBox))    {
  157.                         if (!SendMessage(NULLWND, TESTMOUSE, 0, 0))
  158.                             break;
  159.                         SendMessage(wnd, SCROLL, dir, 0);
  160.                     }
  161.                     return TRUE;
  162.                 }
  163.             }
  164.             if (TestAttribute(wnd, HSCROLLBAR) &&
  165.                 (HScrolling || my == WindowHeight(wnd)-1))    {
  166.                 /* -------- in the bottom border ------- */
  167.                 if (mx == 0 || my == ClientWidth(wnd)+1)
  168.                     /* ------  outside the scroll bar ---- */
  169.                     break;
  170.  
  171.                 HScrolling = TRUE;
  172.  
  173.                 if (mx == 1)    {
  174.                     SendMessage(wnd, HORIZSCROLL, FALSE, 0);
  175.                     return TRUE;
  176.                 }
  177.                 if (mx == WindowWidth(wnd)-2)    {
  178.                     SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  179.                     return TRUE;
  180.                 }
  181.                 if (mx-1 != wnd->HScrollBox)    {
  182.                     int dir = mx-1 > wnd->HScrollBox;
  183.                     while (dir ? (mx-1 > wnd->HScrollBox) :
  184.                                  (mx-1 < wnd->HScrollBox))    {
  185.                         if (!SendMessage(NULLWND, TESTMOUSE, 0, 0))
  186.                             break;
  187.                         SendMessage(wnd, HORIZSCROLL, dir, 0);
  188.                     }
  189.                     return TRUE;
  190.                 }
  191.             }
  192.             break;
  193.         case BUTTON_RELEASED:
  194.             HScrolling = VScrolling = FALSE;
  195.             break;
  196.         case SCROLL:
  197.             if (isVisible(wnd))    {
  198.                 if (p1 == 0)    {
  199.                     if (wnd->wtop == 0)
  200.                         return FALSE;
  201.                 }
  202.                 else if (wnd->wtop+ClientHeight(wnd) >= wnd->wlines)
  203.                     return FALSE;
  204.                 if (p1)
  205.                     wnd->wtop++;
  206.                 else
  207.                     --wnd->wtop;
  208.                 SendMessage(wnd, PAINT, 0, 0);
  209.                 return TRUE;
  210.             }
  211.             break;
  212.         case HORIZSCROLL:
  213.             if (p1 == 0 && wnd->wleft == 0)
  214.                 return FALSE;
  215.             if (p1)    {
  216.                 if (wnd->wleft + ClientWidth(wnd)-1 >= wnd->textwidth)
  217.                     return FALSE;
  218.                 wnd->wleft++;
  219.             }
  220.             else
  221.                 --wnd->wleft;
  222.             SendMessage(wnd, PAINT, 0, 0);
  223.             return TRUE;
  224.         case PAINT:
  225.             if (isVisible(wnd) && wnd->wlines)    {
  226.                 RECT rc;
  227.                 int y;
  228.  
  229.                 if ((RECT *)p1 == NULL)
  230.                     rc = SetRect(0, 0, ClientWidth(wnd)-1,
  231.                                         ClientHeight(wnd)-1);
  232.                 else
  233.                     rc = *(RECT *)p1;
  234.  
  235.                 for (y = RectTop(rc); y <= RectBottom(rc); y++)    {
  236.                     if (y < wnd->wlines-wnd->wtop)
  237.                         WriteTextLine(wnd, &rc, y, FALSE);
  238.                     else    {
  239.                         char line[SCREENWIDTH];
  240.                         memset(line, ' ', sizeof line);
  241.                         line[RectRight(rc)+1] = '\0';
  242.                         SetStandardColor(wnd);
  243.                         writeline(wnd, line+RectLeft(rc),
  244.                                 RectLeft(rc), y, FALSE);
  245.                     }
  246.                 }
  247.                 if (TestAttribute(wnd, VSCROLLBAR))    {
  248.                     int pagelen = wnd->wlines - ClientHeight(wnd);
  249.                     int barlen = ClientHeight(wnd)-2;
  250.                     int lines_tick;
  251.  
  252.                     if (pagelen < 1)
  253.                         wnd->VScrollBox = 1;
  254.                     else    {
  255.                         if (pagelen > barlen)
  256.                             lines_tick = pagelen / barlen;
  257.                         else
  258.                             lines_tick = barlen / pagelen;
  259.                         wnd->VScrollBox = 1 + (wnd->wtop / lines_tick);
  260.                         if (wnd->VScrollBox > ClientHeight(wnd)-2 ||
  261.                                 wnd->wtop + ClientHeight(wnd) >= wnd->wlines)
  262.                             wnd->VScrollBox = ClientHeight(wnd)-2;
  263.                     }
  264.                     SendMessage(wnd, BORDER, p1, 0);
  265.                 }
  266.                 if (TestAttribute(wnd, HSCROLLBAR))    {
  267.                     int pagewidth = wnd->textwidth - ClientWidth(wnd);
  268.                     int barlen = ClientWidth(wnd)-2;
  269.                     int chars_tick;
  270.  
  271.                     if (pagewidth < 1)
  272.                         wnd->HScrollBox = 1;
  273.                     else     {
  274.                         if (pagewidth > barlen)
  275.                             chars_tick = pagewidth / barlen;
  276.                         else
  277.                             chars_tick = barlen / pagewidth;
  278.                         wnd->HScrollBox = 1 + (wnd->wleft / chars_tick);
  279.                         if (wnd->HScrollBox > ClientWidth(wnd)-2 ||
  280.                                 wnd->wleft + ClientWidth(wnd) >= wnd->textwidth)
  281.                             wnd->HScrollBox = ClientWidth(wnd)-2;
  282.                     }
  283.                     SendMessage(wnd, BORDER, p1, 0);
  284.                 }
  285.                 return FALSE;
  286.             }
  287.             break;
  288.         case CLOSE_WINDOW:
  289.             SendMessage(wnd, CLEARTEXT, 0, 0);
  290.             break;
  291.         default:
  292.             break;
  293.     }
  294.     return BaseWndProc(TEXTBOX, wnd, msg, p1, p2);
  295. }
  296.  
  297. char *TextLine(WINDOW wnd, int selection)
  298. {
  299.     char *cp = wnd->text;
  300.     if (selection == -1)
  301.         return NULL;
  302.     while (selection--)    {
  303.         while (*cp != '\n')
  304.             cp++;
  305.         cp++;
  306.     }
  307.     return cp;
  308. }
  309.  
  310. static char *GetTextLine(WINDOW wnd, int selection)
  311. {
  312.     char *line;
  313.     int len = 0;
  314.     char *cp, *cp1;
  315.     cp = cp1 = TextLine(wnd, selection);
  316.     while (*cp && *cp != '\n')    {
  317.         len++;
  318.         cp++;
  319.     }
  320.     line = malloc(len+6);
  321.     if (line != NULL)    {
  322.         memmove(line, cp1, len);
  323.         line[len] = '\0';
  324.     }
  325.     return line;
  326. }
  327.  
  328. void WriteTextLine(WINDOW wnd, RECT *rcc, int y, int reverse)
  329. {
  330.     int len = 0;
  331.     int dif = 0;
  332.     char line[100];
  333.     RECT rc;
  334.     char *lp, *svlp;
  335.     int lnlen;
  336.     int i;
  337.     int trunc = FALSE;
  338.  
  339.     lp = svlp = GetTextLine(wnd, wnd->wtop+y);
  340.     lnlen = LineLength(lp);
  341.  
  342.     /* -------- insert block color change controls ------- */
  343.     if (BlockMarked(wnd))    {
  344.         int bbl = wnd->BlkBegLine;
  345.         int bel = wnd->BlkEndLine;
  346.         int bbc = wnd->BlkBegCol;
  347.         int bec = wnd->BlkEndCol;
  348.         int by = y+wnd->wtop;
  349.  
  350.         if (bbl > bel)    {
  351.             swap(bbl, bel);
  352.             swap(bbc, bec);
  353.         }
  354.         if (bbl == bel && bbc > bec)
  355.             swap(bbc, bec);
  356.  
  357.         if (by >= bbl && by <= bel)    {
  358.             /* ------ the block includes this line ----- */
  359.             int blkbeg = 0;
  360.             int blkend = lnlen;
  361.             if (!(by > bbl && by < bel))    {
  362.                 /* --- the entire line is not in the block --- */
  363.                 if (by == bbl)
  364.                     /* ---- the block begins on this line ---- */
  365.                     blkbeg = bbc;
  366.                 if (by == bel)
  367.                     /* ---- the block ends on this line ---- */
  368.                     blkend = bec;
  369.             }
  370.             memmove(lp+blkend+1, lp+blkend, strlen(lp+blkend)+1);
  371.             lp[blkend] = RESETCOLOR;
  372.             memmove(lp+blkbeg+3, lp+blkbeg, strlen(lp+blkbeg)+1);
  373.             lp[blkbeg] = CHANGECOLOR;
  374.             SetReverseColor(wnd);
  375.             lp[blkbeg+1] = foreground | 0x80;
  376.             lp[blkbeg+2] = background | 0x80;
  377.             lnlen += 4;
  378.         }
  379.     }
  380.  
  381.     for (i = 0; i < wnd->wleft+3; i++)
  382.         if (*(unsigned char *)(lp + i) == RESETCOLOR)
  383.             break;
  384.     if (i < wnd->wleft+3)    {
  385.         if (wnd->wleft+4 > lnlen)
  386.             trunc = TRUE;
  387.         else 
  388.             lp += 4;
  389.     }
  390.     else     {
  391.         for (i = 0; i < wnd->wleft; i++)    {
  392.             if (*(unsigned char *)(lp + i) == CHANGECOLOR)    {
  393.                 *(lp+wnd->wleft+2) = *(lp+i+2);
  394.                 *(lp+wnd->wleft+1) = *(lp+i+1);
  395.                 *(lp+wnd->wleft) = *(lp+i);
  396.                 break;
  397.             }
  398.         }
  399.     }
  400.  
  401.     if (!trunc)    {
  402.         if (lnlen < wnd->wleft)
  403.             lnlen = 0;
  404.         else
  405.             lp += wnd->wleft;
  406.  
  407.         if (rcc == NULL)
  408.             rc = SetRect(0, 0, ClientWidth(wnd)-1, ClientHeight(wnd)-1);
  409.         else
  410.             rc = *rcc;
  411.  
  412.         if (y < rc.tp || y > rc.bt)
  413.             return;
  414.  
  415.         if (lnlen > RectLeft(rc))    {
  416.             lp += RectLeft(rc);
  417.             lnlen = LineLength(lp);
  418.             len = min(lnlen, RectWidth(rc));
  419.             lnlen = LineLength(lp);
  420.             dif = strlen(lp) - lnlen;
  421.             len += dif;
  422.             if (len > 0)
  423.                 strncpy(line, lp, len);
  424.         }
  425.     }
  426.  
  427.     while (len < RectWidth(rc)+dif)
  428.         line[len++] = ' ';
  429.     line[len] = '\0';
  430.  
  431.     dif = 0;
  432.     if (reverse)    {
  433.         char *cp = line;
  434.         SetReverseColor(wnd);
  435.         while ((cp = strchr(cp, CHANGECOLOR)) != NULL)    {
  436.             cp += 2;
  437.             *cp++ = background | 0x80;
  438.         }
  439.         if (*(unsigned char *)line == CHANGECOLOR)
  440.             dif = 3;
  441.     }
  442.     else
  443.         SetStandardColor(wnd);
  444.     writeline(wnd, line+dif, RectLeft(rc), y, FALSE);
  445.     if (svlp != NULL)
  446.         free(svlp);
  447. }
  448.  
  449. void SetTextBlock(WINDOW wnd, int l1, int c1, int l2, int c2)
  450. {
  451.     wnd->BlkBegLine = l1;
  452.     wnd->BlkBegCol  = c1;
  453.     wnd->BlkEndLine = l2;
  454.     wnd->BlkEndCol  = c2;
  455. }
  456.  
  457.